import Base64 from '../libs/Base64.js';
import Crypto from '../libs/crypto.js';
import '../libs/hmac.js';
import '../libs/sha1.js';
import __config from '@/config/env';
/**
 * 通用上传器 (STS版本)
 * @description 接收临时路径上传到oss,使用STS临时凭证方式上传
 * @param {String} filePath - 临时路径(例如: http://tmp/24f3.png)
 * @param {String} dir - 文件目录(例如: wechat/test)
 * @param {String} name - 文件名及后缀(例如: phone.png)
 * @param {Function} success - 成功回调
 * @param {Function} fail - 失败回调
 * @return void
 */
const uploadFile = function(params) {
    // 这里可以做一些文件判断及错误处理
    // 如果文件不合规,直接返回return结束函数不要往下走
    // ...

    // 设置文件上传至OSS后的文件路径(根据需求进行拼接url)
    const aliyunFileKey = `${params.dir}/${params.name}`;

    // 获取STS临时凭证
    getSTSToken(aliyunFileKey).then(stsData => {
        // 使用后端返回的endpoint而不是配置文件中的uploadImageUrl
        const aliyunServerURL = `https://${stsData.bucketName}.${stsData.endpoint}`;

        // 生成policy和signature
        const policyBase64 = getPolicyBase64();
        const signature = getSignature(policyBase64, stsData);

        // 可在这里打印查看一些参数
        console.log(`[完整路径] ${stsData.domain}/${aliyunFileKey}`)
        // ...

        // oss要求的参数详见文档:https://help.aliyun.com/document_detail/39523.

        uni.uploadFile({
            url: aliyunServerURL, //阿里云OSS地址(支持自定义域名)
            filePath: params.filePath, //临时路径
            name: 'file', //固定写法
            formData: { //STS临时凭证参数，从stsData.data中获取
                'key': aliyunFileKey,
                'policy': policyBase64,
                'OSSAccessKeyId': stsData.accessKeyId,
                'signature': signature,
                'success_action_status': '200',
                'x-oss-security-token': stsData.securityToken // STS特有的安全令牌
            },
            // 上传成功
            success: (res) => {
                // 失败回调
                if (res.statusCode != 200) {
                    if (params.fail) {
                        params.fail(res)
                    }
                    return;
                }
                // 成功回调
                if (params.success) {
                    params.success({
                        code: 200,
                        msg: '上传成功', //状态码
                        oss_url: stsData.domain, //使用后端返回的域名
                        oss_file: `${stsData.domain}/${aliyunFileKey}`, //完整上传路径
                        bucket: stsData.bucketName,
                        endpoint: stsData.endpoint
                    });
                }
            },
            // 上传失败
            fail: (err) => {
                err.wxaddinfo = aliyunServerURL;
                if (params.fail) {
                    params.fail(err)
                }
            },
        })
    }).catch(err => {
        console.error('获取STS凭证失败', err);
        if (params.fail) {
            params.fail({
                errMsg: '获取STS凭证失败'
            })
        }
    });
}

/**
 * 获取STS临时凭证
 * @return Promise
 */
const getSTSToken = function(path) {
    return new Promise((resolve, reject) => {
        // 这里需要调用你自己的后端接口获取STS临时凭证
        // 示例使用 uni.request 请求后端接口
        uni.request({
            url: __config.basePath + '/upms/file/getOssTempCredential', // 替换为你的后端接口地址
            method: 'POST',
            header: {
                'Content-Type': 'application/json',
                'tenant-id': __config.tenantId
            },
            data: {
                "fileDir": path
            },
            success: (res) => {
                // 根据后端返回结构，数据在res.data.data中
                if (res.statusCode === 200 && res.data && res.data.code === 0 && res.data
                    .data) {
                    // 直接返回data中的STS信息
                    resolve(res.data.data);
                } else {
                    reject(new Error('获取STS凭证失败'));
                }
            },
            fail: (err) => {
                reject(err);
            }
        });
    });
}

/**
 * 生成Policy签名
 * @return String
 */
const getPolicyBase64 = function() {
    let date = new Date();
    date.setHours(date.getHours() + 1); // 设置1小时后过期
    let srcT = date.toISOString();
    const policyText = {
        "expiration": srcT,
        "conditions": [
            ["content-length-range", 0, 10 * 1024 * 1024] // 设置上传文件的大小限制,10mb
        ]
    };
    return Base64.encode(JSON.stringify(policyText));
}

/**
 * 生成签名
 * @param {String} policyBase64 - Base64编码的policy
 * @param {Object} stsData - STS数据对象
 * @return String
 */
const getSignature = function(policyBase64, stsData) {
    // 使用Crypto库生成签名
    const bytes = Crypto.HMAC(Crypto.SHA1, policyBase64, stsData.accessKeySecret, {
        asBytes: true
    });
    const signature = Crypto.util.bytesToBase64(bytes);
    return signature;
}

// 修改为ES6模块导出方式
export default uploadFile;